package me.magicall.db.dao2;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import me.magicall.db.Condition;
import me.magicall.db.FieldComparator;
import me.magicall.db.util.AboutNull;
import me.magicall.db.util.PageInfo;

/**
 * 一个数据传输对象。
 * 
 * @author MaGiCalL
 * @param <T> 最终返回结果对象的类型
 */
public class Query<T> {

	private String mainModelName;
	private final Collection<String> otherModelsNames = new HashSet<String>();
	/**
	 * 抛弃model或结果中为null的字段。
	 * 对于insert/update，抛弃意味着使用数据库自己的默认值，如果数据库没有设置该字段的默认值，通常数据库会抛出异常。
	 * 对于select，会将数据库中值为null的字段置为一个默认值。数字型的置为0，字符串型的置为""（空字符串），boolean置为false，char置为空格，时间置为new Date(0L)
	 */
	private AboutNull aboutNull;
	/**
	 * 一个Comparator，用来给结果排序，在sql里会用来构建成order by 子句。
	 */
	private FieldComparator<? super T> fieldComparator;
	/**
	 * 用来分页的东西，最终会用来构建成limit子句。
	 */
	private PageInfo pageInfo;
	/**
	 * 多个model，支持model.id这种语法，支持驼峰式命名、下划线命名，支持名词所有格（'s）命名法、空格命名法。
	 * 例：
	 * 普通：user.name
	 * 驼峰式命名：userBorn.birthDay
	 * 下划线(db风格)命名：user_born.birth_month,user_Born.birth_Year
	 * 名词所有格命名法：user's age（相当于user.age）
	 * 空格命名法：user born.home town（相当于userBorn.homeTown）
	 * 在sql中最终会构成select子句、from子句。
	 */
	/**
	 * 条件，在sql中最终会用来构建成where子句。
	 */
	private List<Condition> conditions;

	private T newValue;

	public FieldComparator<? super T> getFieldComparator() {
		return fieldComparator;
	}

	public void setFieldComparator(final FieldComparator<? super T> fieldComparator) {
		this.fieldComparator = fieldComparator;
	}

	public PageInfo getPageInfo() {
		return pageInfo;
	}

	public void setPageInfo(final PageInfo pageInfo) {
		this.pageInfo = pageInfo;
	}

	private List<Condition> checkConditions() {
		if (conditions == null) {
			conditions = new ArrayList<Condition>();
		}
		return conditions;
	}

	public List<Condition> getConditions() {
		return conditions;
	}

	public void setConditions(final Condition... conditions) {
		addConditions(conditions);
	}

	public void setConditions(final List<Condition> conditions) {
		this.conditions = conditions;
	}

	public void addConditions(final Condition... conditions) {
		checkConditions();
		for (final Condition t : conditions) {
			this.conditions.add(t);
		}
	}

	public void addConditions(final List<Condition> conditions) {
		checkConditions().addAll(conditions);
	}

	public String getMainModelName() {
		return mainModelName;
	}

	public void setMainModelName(final String mainModelName) {
		this.mainModelName = mainModelName;
	}

	public AboutNull getAboutNull() {
		return aboutNull;
	}

	public void setAboutNull(final AboutNull aboutNull) {
		this.aboutNull = aboutNull;
	}

	public Collection<String> getOtherModelsNames() {
		return otherModelsNames;
	}

	public void addOtherModelsNames(final String... otherModelsNames) {
		for (final String name : otherModelsNames) {
			this.otherModelsNames.add(name);
		}
	}

	public T getNewValue() {
		return newValue;
	}

	public void setNewValue(final T newValue) {
		this.newValue = newValue;
	}
}
